#ifndef SERVER_H
#define SERVER_H

#include "common.h"

/*
C11标准引入了 <stdatomic.h> 头文件，用于提供一组原子操作，保证在多线程环境下的安全性和性能。
掌握 <stdatomic.h> 库的功能对于编写高效且可靠的并发程序至关重要。
*/
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>

#include "adb/adb_tunnel.h"
#include "coords.h"
#include "options.h"
#include "util/intr.h"
#include "util/log.h"
#include "util/net.h"
#include "util/thread.h"

#define SC_DEVICE_NAME_FIELD_LENGTH 64

/* android设备的信息 */
struct sc_server_info {
    /* Android设备的型号 红米Note9Pro显示 M2007J17C */
    char device_name[SC_DEVICE_NAME_FIELD_LENGTH];
};

// android服务端初始化参数，注释参考 scrcpy_options
struct sc_server_params {
    uint32_t scid;

    // 需要连接的android设备的序列号，多个Android设备连接时可能用到
    const char *req_serial;
    enum sc_log_level log_level;
    enum sc_codec video_codec;
    enum sc_codec audio_codec;
    // Android设备的视频采集来源。默认是屏幕
    enum sc_video_source video_source;
    // Android设备的音频采集来源，默认自动选择
    enum sc_audio_source audio_source;
    // 选择采集视频的摄像头
    enum sc_camera_facing camera_facing;
    // 被复制
    const char *crop;
    const char *video_codec_options;
    const char *audio_codec_options;
    const char *video_encoder;
    const char *audio_encoder;
    const char *camera_id;
    // 设置摄像头视频采集的分辨率
    const char *camera_size;
    // 设置摄像头采集摄像头的宽高比
    const char *camera_ar;
    uint16_t camera_fps;
    struct sc_port_range port_range;
    uint32_t tunnel_host;
    uint16_t tunnel_port;
    uint16_t max_size;
    uint32_t video_bit_rate;
    uint32_t audio_bit_rate;
    const char *max_fps; // float to be parsed by the server
    int8_t lock_video_orientation;
    // true代表可以用鼠标键盘控制连接的android设备，false代表只演示，不能用PC控制
    bool control;
    uint32_t display_id;
    bool video;
    // 是否禁止音频转发，默认false，true则音频转发，并且不在PC上播放
    bool audio;
    bool audio_dup;
    // 在Android设备上的物理触摸在PC窗体上展示出来，默认值为false
    bool show_touches;
    // Android设备一直保持常亮屏状态，屏幕会暗下来，但是不会锁屏，默认是false。
    bool stay_awake;
    bool force_adb_forward;
     // 是否在关闭scrcpy时自动关闭Android设备的屏幕，默认是false
    bool power_off_on_close;
    bool clipboard_autosync;
    bool downsize_on_error;
    // 是否采用TCPIP方式连接android设备，不填IP：PORT时将尝试自动扫描wifi连接
    bool tcpip;
    // Android设备的IP地址和端口号，端口号默认5555。默认为NULL
    const char *tcpip_dst;

    // 是否采用USB方式连接android设备,仅有一个Android设备通过USB方式连接PC时生效
    bool select_usb;

    // 是否采用TCPIP方式连接android设备,仅有一个Android设备通过wifi方式连接PC时生效
    bool select_tcpip;
    bool cleanup;
    // 设置启动时是否启动Android设备的屏幕
    bool power_on;
    bool kill_adb_on_close;
    bool camera_high_speed;
    // 获取Android设备的某些信息，打印完成后即退出。参考--list-*类的命令行选项
    uint8_t list;
};

/* android服务端上下文 */
struct sc_server {
    // The internal allocated strings are copies owned by the server
    struct sc_server_params params;

    // 设备的序列号,wifi连接时代表设备的IP地址及端口号
    char *serial;
    char *device_socket_name;

    // 正在进行中的进程？
    sc_thread thread;

    // Android设备的信息，仅在连接时初始化一次
    struct sc_server_info info; // initialized once connected

    // 辅助互斥锁
    sc_mutex mutex;
    // 辅助信号量
    sc_cond cond_stopped;

    // 指示Android服务端是不是已经停止了
    bool stopped;
    
    // 辅助可中断器
    struct sc_intr intr;
    // 通道上下文,用于连接android设备
    struct sc_adb_tunnel tunnel;

    // 视频socket，视频数据通过这个传过来。总要初始化
    sc_socket video_socket;
    // 音频socket
    sc_socket audio_socket;
    // 控制信息socket。仅演示屏幕不能用鼠标键盘控制的情况下不进行初始化
    sc_socket control_socket;

    // 服务连接事件回调函数
    const struct sc_server_callbacks *cbs;
    // 回调用到的用户数据，目前全部为NULL
    void *cbs_userdata;
};

/* adb server 服务端连接事件的回调函数 */
struct sc_server_callbacks {
    /**
     * Called when the server failed to connect
     *
     * If it is called, then on_connected() and on_disconnected() will never be
     * called.
     */
    void (*on_connection_failed)(struct sc_server *server, void *userdata);

    /**
     * Called on server connection
     */
    void (*on_connected)(struct sc_server *server, void *userdata);

    /**
     * Called on server disconnection (after it has been connected)
     */
    void (*on_disconnected)(struct sc_server *server, void *userdata);
};

/*
 * init the server with the given params。
    用给定的参数初始化服务端上下文，只是简单初始化一些参数
 * @param server 服务端上下文
 * @param params 服务端初始化参数
 * @param cbs 设备连接事件的回调函数
 * @param cbs_userdata 回调函数的用户数据，当前方法一直传NULL
 * @return 成功返回true,否则返回false
 */
bool
sc_server_init(struct sc_server *server, const struct sc_server_params *params,
               const struct sc_server_callbacks *cbs, void *cbs_userdata);

/* 
start the server asynchronously。 异步开启android设备上的服务
@param server 服务端上下文配置参数
@return 成功返回true，否则返回false
*/
bool
sc_server_start(struct sc_server *server);

// disconnect and kill the server process
// @param server 服务端上下文
void
sc_server_stop(struct sc_server *server);

// join the server thread
void
sc_server_join(struct sc_server *server);

// close and release sockets
// @param server 配置参数
void
sc_server_destroy(struct sc_server *server);

#endif
